﻿namespace EFS.RC.CC.Config.Scheduler
{
	public class Settings : EFS.Common.Serialization.ISerializable, EFS.Common.ISelfDescriptor, System.Collections.Generic.IEnumerable<EFS.RC.CC.Config.Scheduler.Exception>
	{
		/// <summary>
		/// Time intervals
		/// </summary>
		private EFS.RC.CC.Config.Scheduler.Exception[] exceptions = new EFS.RC.CC.Config.Scheduler.Exception[0];

		/// <summary>
		/// Week
		/// </summary>
		private EFS.RC.CC.Config.Scheduler.Week week = new EFS.RC.CC.Config.Scheduler.Week();

		/// <summary>
		/// Defalt Handler
		/// </summary>
		public EFS.RC.CC.Config.Scheduler.TimeInterval.Handlers DefaultHandler { get; private set; }

		/// <summary>
		/// 
		/// </summary>
		private System.DateTime loadedOn = System.DateTime.Now;

		/// <summary>
		/// Constructor
		/// </summary>
		public Settings()
		{
			// default
			DefaultHandler = TimeInterval.Handlers.AfterHours;
		}

		/// Serialize
		public void Serialize(EFS.Common.Serialization.XmlWriter xmlWriter)
		{
			// write
			xmlWriter.Write("DefaultHandler", System.Enum.GetName(typeof(EFS.RC.CC.Config.Scheduler.TimeInterval.Handlers), DefaultHandler));
			xmlWriter.Write("Week", week);
			xmlWriter.Write<EFS.RC.CC.Config.Scheduler.Exception>("Exceptions", "Exception", exceptions);
		}

		/// Deserialize
		public void Deserialize(EFS.Common.Serialization.XmlReader xmlReader)
		{
			// read
			DefaultHandler = (EFS.RC.CC.Config.Scheduler.TimeInterval.Handlers)System.Enum.Parse(typeof(EFS.RC.CC.Config.Scheduler.TimeInterval.Handlers), xmlReader.Read("DefaultHandler"));
			xmlReader.Read("Week", week);
			xmlReader.Read<EFS.RC.CC.Config.Scheduler.Exception>("Exceptions", "Exception", ref exceptions);
		}

		/// <summary>
		/// Get enumerator
		/// </summary>
		/// <returns></returns>
		public System.Collections.IEnumerator GetEnumerator()
		{
			return exceptions.GetEnumerator();
		}

		/// <summary>
		/// Get enumerator
		/// </summary>
		/// <returns></returns>
		System.Collections.Generic.IEnumerator<EFS.RC.CC.Config.Scheduler.Exception> System.Collections.Generic.IEnumerable<EFS.RC.CC.Config.Scheduler.Exception>.GetEnumerator()
		{
			return (System.Collections.Generic.IEnumerator<EFS.RC.CC.Config.Scheduler.Exception>)exceptions.GetEnumerator();
		}

		#region Loading

		// Make path
		private static System.String FilePath
		{
			get
			{
				// make path
				return EFS.Common.Directory.MapApplicationPath("EFS.RC.CC.Scheduler.xml");
			}
		}

		/// <summary>
		/// get current settings
		/// </summary>
		private static Settings current = null;
		public static Settings Current
		{
			get
			{
				// check
				if (null == current)
				{
					// make new
					current = new Settings();

					// load injections
					System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
					try
					{
						// load document
						xmlDocument.Load(FilePath);

						// read
						EFS.Common.Serialization.XmlReader xmlReader = new EFS.Common.Serialization.XmlReader(xmlDocument.InnerXml);
						xmlReader.Read("Scheduler", current);
						xmlReader.Close();

					}
					catch (System.Exception e)
					{
						EFS.EventLog.Log.LogException(e, null);
					}
				}
				else
				{
					// check loaded time
					if (current.loadedOn < System.DateTime.Now.AddMinutes(-1))
					{
						// clean
 						current = null;
						
						// reload
						return Current;
					}
				}

				// get
				return current;
			}
		}

		#endregion

		/// <summary>
		/// Describe
		/// </summary>
		/// <returns></returns>
		public System.String Describe()
		{
			// sb
			System.Text.StringBuilder sb = new System.Text.StringBuilder();

			// get current handler
			switch (GetCurrentHandler)
			{
				case TimeInterval.Handlers.AfterHours: sb.AppendLine("Current handler is ~After Hours~"); break;
				case TimeInterval.Handlers.Hunt: sb.AppendLine("Current handler is ~Hunter~"); break; 
			}

			// done
			return sb.ToString();
		}

		/// <summary>
		/// Get current handler
		/// </summary>
		public EFS.RC.CC.Config.Scheduler.TimeInterval.Handlers GetCurrentHandler
		{
			get
			{
				// currnt settings
				Settings current = Current;

				// now
				System.DateTime now = System.DateTime.Now;
			
				// day
				EFS.RC.CC.Config.Scheduler.Day day = null;

				// check exceptions
				foreach (EFS.RC.CC.Config.Scheduler.Exception exception in current)
				{
					if (exception.Date == now.Date)
					{
						day = exception;
						break;
					}
				}

				// get day
				if (null == day)
				{
					day = week.Day(now.DayOfWeek);
				}

				// check
				if (null != day)
				{
					// now find interval
					foreach (EFS.RC.CC.Config.Scheduler.TimeInterval timeInterval in day)
					{
						if (timeInterval.StartTime.DateTime <= now && timeInterval.FinishTime.DateTime >= now)
						{
							return timeInterval.Handler;
						}
					}
				}

				// none
				return DefaultHandler;
			}
		}
	}
}